package com.njzxw.fs.commonutil.web.aspect;

import com.alibaba.druid.wall.WallFilter;
import com.njzxw.fs.commonutil.bean.BaseBean;
import com.njzxw.fs.commonutil.bean.BaseUserBean;
import com.njzxw.fs.commonutil.bean.LogBean;
import com.njzxw.fs.commonutil.util.GsonUtil;
import com.njzxw.fs.commonutil.util.ReflectUtil;
import com.njzxw.fs.commonutil.util.StringHelper;
import com.njzxw.fs.commonutil.util.UserUtil;
import com.njzxw.fs.commonutil.web.BaseController;
import com.njzxw.fs.commonutil.web.ReturnMap;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.util.PropertyFilter;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Aspect
@Component
public class ParamsValidation extends BaseController{

    public org.slf4j.Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    protected ReturnMap returnMap;

    @Autowired
    protected BaseUserBean baseUserBean;

    @Autowired
    protected UserUtil userUtil;

    @Pointcut("execution(* com.njzxw.*.*..controller..*.*(..))")
    public void aspect(){    }

    @Around("aspect()")
    public void around(ProceedingJoinPoint jp){
        long start_time = System.currentTimeMillis();
        String methodName = jp.getSignature().getName();
        Object[] obj = jp.getArgs();
        Object target = jp.getTarget();
        logger = LoggerFactory.getLogger(target.getClass());

        int cnt = obj.length;
        HttpServletResponse response = null;
        HttpServletRequest request = null;
        BindingResult bindingResult = null;
        Throwable ex = null;
        ReturnMap returnMap = null;
        BaseBean baseBean = null;
        Object objs = null;
        boolean isSucc = false;
        String pasams = "";
        long end_time = 0;
        try {

            for(int i=0;i<cnt;i++){

                if(obj[i] instanceof HttpServletResponse){
                    response = (HttpServletResponse) obj[i];
                }

                if(obj[i] instanceof HttpServletRequest){
                    request = (HttpServletRequest) obj[i];
                }

                if(obj[i] instanceof BindingResult){
                    bindingResult = (BindingResult) obj[i];

                    if(bindingResult.hasErrors()){
                        List<ObjectError> ls = bindingResult.getAllErrors();

                        if(!ls.isEmpty()){
                            returnMap = new ReturnMap();
                            returnMap = returnMap.getErrorReturnMap(ls.get(0).getDefaultMessage());
                        }
                    }

                }

                if(obj[i] instanceof BaseBean){

                    baseBean = (BaseBean) obj[i];
                    if(baseBean != null){
//                        logger.debug("beaseBean1:"+baseBean);
////                        ReflectUtil.nullConverStringNull(obj[i]);
//                        logger.debug("beaseBean2:"+baseBean);
                        pasams = baseBean.toString();

                        baseUserBean.setOper_id(baseBean.getOper_id());
                        baseUserBean.setToken(baseBean.getToken());

                        orderBy(baseBean);

//                        manageOrg(baseBean);

                        MDC.put("hascode",String.valueOf(baseBean.hashCode()));
                        MDC.put("pageNum",String.valueOf(baseBean.getPageNum()));
                        MDC.put("pageSize",String.valueOf(baseBean.getPageSize()));
                        MDC.put("orderBy",String.valueOf(baseBean.getOrderBy()));
                        MDC.put("isRole",userUtil.checkRedisRoleExist("1")?"1":userUtil.checkRedisRoleExist("2")?"2":"3");
                        baseBean.setPageNum(null);
                        baseBean.setPageSize(null);
                        baseBean.setOrderBy(null);

                    }

                }

            }

            if(returnMap == null){
                objs = jp.proceed();
                isSucc = true;
                if(objs == null){
                    returnMap = this.returnMap;
                }else{
                    returnMap = (ReturnMap) objs;
                }
            }
        } catch (Throwable throwable) {
            ex = throwable;
        } finally {
            if(baseBean == null){
                baseBean = new BaseBean();
            }
            end_time = System.currentTimeMillis();
            String state = "";
            if(ex != null){
                logger.error("执行方法【" + methodName + "】,执行时间："+(end_time-start_time)+"ms,请求参数信息："+pasams+"， 异常信息: " + ex,ex);
                if(returnMap == null){
                    returnMap = new ReturnMap();
                    returnMap = returnMap.getErrorReturnMap("可能最近访问人有点多，服务器有点累了，休息一会儿，马上回来。");
                    state = "访问出错";
                }
            }else{
                if(returnMap == null){
                    returnMap = new ReturnMap();
                    state = "访问异常";
                    logger.error("执行方法【" + methodName + "】,执行时间："+(end_time-start_time)+"ms,请求参数信息："+pasams+"， 异常信息: " + ex,ex);
                }else{
                    state = "正常";
                    logger.info("执行方法【"+methodName+"】,执行时间："+(end_time-start_time)+"ms,请求参数信息："+pasams+"，返回值："+returnMap.getReturnMap().toString());
                }

            }

            if(request != null){
                String url = request.getRequestURI();
                logger.debug("url:"+url);
                LogBean logBean = new LogBean();
                logBean.setOper_url(url);
                logBean.setOper_id(baseBean.getOper_id());
                Map<String,Object> map = userUtil.getUserRep().getLogRemark(logBean);
                logger.debug("logbean:"+logBean.toString());
                if(map != null && !map.isEmpty()){
                    logBean.setOper_name(StringHelper.get(map,"open_name"));
                    logBean.setOper_remark(StringHelper.get(map,"remark"));
                    logBean.setRequest_params(pasams);
                    logBean.setReturn_str(returnMap.getReturnMap().toString());
                    logBean.setState(state);
                    logBean.setType(baseBean.getRequset_type());
                    userUtil.getUserRep().insertLog(logBean);
                }
            }

            if(objs != null){
                this.writeJsonDataNoNull(returnMap,response);
            } else {
                if(returnMap != null && !isSucc){
                    this.writeJsonDataNoNull(returnMap,response);
                }
            }
        }

    }

    public void manageOrg(BaseBean baseBean){
//        logger.debug("==============="+userUtil.checkRedisManageOrg());
        if(userUtil.checkRedisRoleExist("1")){//是否是系统管理员，系统管理员直接能查询所有
            baseBean.setManage_org_table_name(null);
            baseBean.setManage_org_table_name_where(null);
        }else if(userUtil.checkRedisRoleExist("2")){//检查是否是部门管理员
            //获取是那个部门的部门管理员
            String manageOrg = userUtil.checkRedisManageOrg();
            baseBean.setManage_org_table_name(",t_manager_user_org a1");
            baseBean.setManage_org_table_name_where("and a.oper_id = a1.manager_user_id and a1.manager_org_id in ("+(manageOrg.substring(1,manageOrg.length()-1))+") ");
        }else{
            baseBean.setManage_org_table_name(null);
            baseBean.setManage_org_table_name_where(" and a.oper_id = "+baseBean.getOper_id());
        }
    }

    public void writeJsonDataNoNull(ReturnMap returnMap, HttpServletResponse response) {
        try {

            Map data = null;
            if (returnMap != null) {
                data = returnMap.getReturnMap();
            }

            response.setContentType("application/json;charset=utf-8");
            response.setCharacterEncoding("utf-8");

//            JsonConfig jsonConfig = new JsonConfig();
//            PropertyFilter filter = new PropertyFilter() {
//                public boolean apply(Object object, String fieldName, Object fieldValue) {
//                    return null == fieldValue;
//                }
//            };
//
//            jsonConfig.setJsonPropertyFilter(filter);

            response.getWriter().print(GsonUtil.parseObjectToJsonString(data));
//            if (data instanceof Map) {
//                JSONObject.fromObject(data,jsonConfig));
//            } else if (data instanceof List) {
//                response.getWriter().print(JSONArray.fromObject(((List) data),jsonConfig));
//            } else {
//                response.getWriter().print(JSONObject.fromObject(data,jsonConfig));
//            }
        } catch (Exception e) {
            logger.debug("返回值失败：", e);
        }
    }

    @Pointcut("execution(* com.njzxw.*.*..repository..*.*(..))")
    public void aspectSql(){    }

    @Around("aspectSql()")
    public Object aroundSql(ProceedingJoinPoint jp){


        String methodName = jp.getSignature().getName();
        Object[] obj = jp.getArgs();
        Object target = jp.getTarget();

        String signature = jp.getSignature().toLongString();
        Class returnTypeClass = ((MethodSignature) jp.getSignature()).getReturnType();
        String returnType = returnTypeClass.getSimpleName();
//        logger.debug("返回类型："+methodName);

        BaseBean baseBean = null;
        int cnt = obj.length;
        for(int i=0;i<cnt;i++) {
            if (obj[i] instanceof BaseBean) {
                baseBean = (BaseBean) obj[i];
//                logger.debug("baseBeanbaseBeanbaseBean:"+baseBean.toString());
                if (baseBean != null) {
                    String hascode = MDC.get("hascode");
                    if (methodName.toLowerCase().contains("page".toLowerCase())&&(String.valueOf(baseBean.hashCode())).equals(hascode)) {
//                        baseBean.setOrderBy("");
                        String objPageNum = MDC.get("pageNum");
                        String objPageSize = MDC.get("pageSize");
                        String objOrderBy = MDC.get("orderBy");
//                        logger.debug("???????====2=:"+objPageNum+"--"+objPageSize+"--"+objOrderBy);
                        if(baseBean.getPageNum() == null && objPageNum != null && !"null".equals(objPageNum)){
                            baseBean.setPageNum(objPageNum == null ? null : Integer.valueOf(objPageNum));
                        }else if(StringUtils.isBlank(objPageNum) && !StringUtils.isBlank(objPageSize)){
                            baseBean.setPageNum(1);
                        }

                        if(baseBean.getPageSize() == null && objPageSize != null && !"null".equals(objPageSize)) {
                            baseBean.setPageSize(objPageNum == null ? null : Integer.valueOf(objPageSize));
                        }

                        if(StringUtils.isBlank(baseBean.getOrderBy())&&objOrderBy != null && !"null".equals(objOrderBy)) {
                            baseBean.setOrderBy(objOrderBy == null ? null : String.valueOf(objOrderBy));
                        }

//                        logger.debug("???????====1=:"+StringUtils.isNotBlank(baseBean.getOrderKey()));
                        if(StringUtils.isNotBlank(baseBean.getOrderKey())){
                            orderBy(baseBean);
                        }

                    }else if(methodName.toLowerCase().contains("page".toLowerCase())){
                        orderBy(baseBean);
                    }
                    if(methodName.toLowerCase().contains("manageorg".toLowerCase())){

                        String isRole = MDC.get("isRole");
                        if("1".equals(isRole)){//是否是系统管理员，系统管理员直接能查询所有
                            baseBean.setManage_org_table_name(null);
                            baseBean.setManage_org_table_name_where(null);
                        }else if("2".equals(isRole)){//检查是否是部门管理员
                            //获取是那个部门的部门管理员
                            String manageOrg = userUtil.checkRedisManageOrg();
                            baseBean.setManage_org_table_name(",t_manager_user_org a1");
                            baseBean.setManage_org_table_name_where("and a.oper_id = a1.manager_user_id and a1.manager_org_id in ("+(manageOrg.substring(1,manageOrg.length()-1))+") ");
                        }else{
                            baseBean.setManage_org_table_name(null);
                            baseBean.setManage_org_table_name_where(" and a.oper_id = "+baseBean.getOper_id());
                        }
                    }
                }
                logger.debug("请求执行sqlbebean参数值:"+baseBean.toString());
            }
        }

        try {
            return jp.proceed();
        } catch (Throwable throwable) {
            logger.error("执行sql出现错误：",throwable);
            if(returnType.equals("List")){
                return null;
            }else if(returnType.equals("Map")){
                return null;
            }else if(returnType.equals("String")){
                return null;
            }else if(returnType.equals("Int")){
                return -1;
            }else if(returnType.equals("Integer")){
                return -1;
            }
        }
        return null;
    }

    public void orderBy(BaseBean baseBean){
        logger.debug("StringUtils.isBlank(baseBean.getOrderKey()) && StringUtils.isBlank(baseBean.getOrderBy()):"+(StringUtils.isBlank(baseBean.getOrderKey()) && StringUtils.isBlank(baseBean.getOrderBy())));
        if(StringUtils.isBlank(baseBean.getOrderKey()) && StringUtils.isBlank(baseBean.getOrderBy())){
            baseBean.setOrderBy(" a.oper_date desc ");
        } else {
            if(StringUtils.isBlank(baseBean.getOrderBy())){
                baseBean.setOrderBy(baseBean.getOrderKey()+"  "+(StringUtils.isBlank(baseBean.getOrderRule())?"":baseBean.getOrderRule()));
            }
        }
    }

}
